﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Security.Permissions;
using MongoDB.Driver;
using System.IO;
using MySQLDriverCS;
using System.Data;
using System.Net;
using System.Text;
using System.Threading;

namespace TrackTool
{
    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    [System.Runtime.InteropServices.ComVisibleAttribute(true)]
    public partial class Form1 : Form
    {
        private static string IP = "mobi03v.add.vnet.qihoo.net";
        private static string USERNAME = "al_uploader";
        private static string PASSWD = "password123";
        private static string DATABASE = "al_data";
        private MySQLConnection conn;


        private MongoClient client_trace;
        private MongoClient client_model;

        private TrainLocData tld;
        private List<LocItem> mLocList = new List<LocItem>();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            string str_url = Application.StartupPath + "\\test.html" ;
            Uri url = new Uri(str_url);
            webBrowser1.Url = url;
            webBrowser1.ObjectForScripting = this;

            client_trace = new MongoClient("mongodb://10.121.97.113:37600");
            client_model = new MongoClient("mongodb://10.121.97.113:7625");

            conn = new MySQLConnection(new MySQLConnectionString(IP, DATABASE, USERNAME, PASSWD).AsString);
        }

        private void AddMarker(double lat, double lng, string iconurl)
        {
            if(lat ==0 || lng == 0)
                return;
            webBrowser1.Document.InvokeScript("addMarker", new object[] { lat, lng, iconurl }); 
        }
        private void ClearMarker()
        {
            webBrowser1.Document.InvokeScript("clearMarker");
        }
        private void SetBounds()
        {
            webBrowser1.Document.InvokeScript("setBounds");
        }
        private void addInfoWindow(double lat, double lng, string info)
        {
            webBrowser1.Document.InvokeScript("addInfoWindow", new object[] { lat, lng, info }); 
        }
        private void addCircle(double lat, double lng, int radius)
        {
            webBrowser1.Document.InvokeScript("addCircle", new object[] { lat, lng, radius }); 
        }


        private void button1_Click(object sender, EventArgs e)
        {
            if (txtDeviceID.Text.Length == 0)
                return;
            getFile(txtDeviceID.Text);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            ClearMarker();
        }

        private void getLocTrace()
        {
            MongoServer server = client_trace.GetServer();
            var db = server.GetDatabase("loc_trace");
            var coll = db.GetCollection<LocItem>("loc_trace");


            var query = new QueryDocument();
            query.Add("device_id", "4fe17cb37753bd17");
            query.Add("date", DateTime.Parse("2013-11-03T00:00:00Z"));
           
            MongoCursor<LocItem> c = coll.FindAs<LocItem>(query);
            foreach (var obj in c)
            {
                AddMarker(obj.lat, obj.lng, "history_dot_small_blue.png");
            }
        }

        private void getFile(string id)
        {
            MongoServer server = client_model.GetServer();
            var db = server.GetDatabase("device_model");
            var coll = db.GetCollection("device_model");


            var query = new QueryDocument();
            query.Add("_id", id);

            //var query = Query.EQ("_id", "4fe17cb37753bd17_w");
            var result = coll.FindOne(query);
            byte[] buf = result.GetElement("data").Value.AsByteArray;
            MemoryStream ms = new MemoryStream();
            ms.Write(buf, 0, buf.Length);

            tld = new TrainLocData();
            tld.ReadRoute(ms);
            Console.Out.Write(buf);
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            listBox2.Items.Clear();
            switch (listBox1.SelectedIndex)
            {
                case 0:
                    if (tld == null || tld.morninglist == null)
                        return;
                    for (int i = 0; i < tld.morninglist.Count; i++)
                    {
                        listBox2.Items.Add("" + i);
                    }
                    break;
                case 1:
                    if (tld == null || tld.noonlist == null)
                        return;
                    for (int i = 0; i < tld.noonlist.Count; i++)
                    {
                        listBox2.Items.Add("" + i);
                    }
                    break;
                case 2:
                    if (tld == null || tld.nightlist == null)
                        return;
                    for (int i = 0; i < tld.nightlist.Count; i++)
                    {
                        listBox2.Items.Add("" + i);
                    }
                    break;
            }
        }

        private void listBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = listBox2.SelectedIndex;
            List<ItemSafeRoute> list = null;
            switch (listBox1.SelectedIndex)
            {
                case 0:
                    list = tld.morninglist;
                    break;
                case 1:
                    list = tld.noonlist;
                    break;
                case 2:
                    list = tld.nightlist;
                    break;
            }
            showRouteInfo(list[index]);
        }

        private void showRouteInfo(ItemSafeRoute obj)
        {
            listBox3.Items.Clear();
            ClearMarker();

            listBox3.Items.Add("SPT: " + LocItemToString(obj.spt));
            listBox3.Items.Add("SPT: " + LocItemToString(obj.ept));
            AddMarker(obj.spt.lat, obj.spt.lng, "history_dot_large_blue.png");
            AddMarker(obj.ept.lat, obj.ept.lng, "history_dot_large_blue.png");

            for (int i = 0; obj.list != null && i < obj.list.Count; i++)
            {
                BASIC_LOC_ITEM item = obj.list[i];
                if (item.cid.cid == 0xffffffff || item.cid.cid == 0xfffffffe)
                    continue;
                listBox3.Items.Add(LocItemToString(item));
                AddMarker(item.lat, item.lng, "history_dot_small_blue.png");
            }
            SetBounds();
        }

        private string LocItemToString(BASIC_LOC_ITEM obj)
        {
            string ret = string.Format("lac={0},cid={1},{2}", obj.cid.lac, obj.cid.cid, obj.tTime.ToShortTimeString());
            return ret;
        }

        private void btnQueryLoc_Click(object sender, EventArgs e)
        {
            string device_id = txtDeviceID_Loc.Text;
            string date = txtDate.Text;

            loadTrackList(device_id, date);
            showTrackList();
        }

        private void loadTrackList(string device_id, string date)
        {
            try
            {
                MongoServer server = client_trace.GetServer();
                var db = server.GetDatabase("loc_trace");
                var coll = db.GetCollection<LocItem>("loc_trace");

                var query = new QueryDocument();
                query.Add("device_id", device_id);
                query.Add("date", DateTime.Parse(string.Format("{0}T00:00:00Z", date)));

                bool b_ct1 = chk_CT1.Checked;

                mLocList.Clear();
                MongoCursor<LocItem> c = coll.FindAs<LocItem>(query);
                foreach (var obj in c)
                {
                    if (b_ct1)
                    {
                        if (obj.c_t == 1)
                            mLocList.Add(obj);
                    }
                    else
                    {
                        mLocList.Add(obj);
                    }
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void showTrackList()
        {
            ClearMarker();
            listBox4.Items.Clear();
            foreach ( var obj in mLocList)
            {
                AddMarker(obj.lat, obj.lng, "history_dot_small_blue.png");
                listBox4.Items.Add(string.Format("{0},{1},{2},{3}", obj.time.ToShortTimeString(), obj.lat, obj.lng, obj.cell_list));
            }
            SetBounds();
        }

        private void listBox4_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBox4.SelectedIndex < 0 || listBox4.SelectedIndex >= listBox4.Items.Count)
                return;
            string text = (string)listBox4.Items[listBox4.SelectedIndex];

            string[] celllist = text.Split(',');
            if (celllist.Length > 0)
            {
                ClearMarker();
                double[] dloc = GeoConvert.encrypt(Double.Parse(celllist[1]), Double.Parse(celllist[2]));
                AddMarker(dloc[0], dloc[1], "history_dot_small_blue.png");

                for (int i = 3; i < celllist.Length; i++ )
                {
                    if (celllist[i].Length > 0 && celllist[i].IndexOf("|") > 0)
                    {
                        string[] objary = celllist[i].Split('|');
                        double[] loc = getLocation(Int32.Parse(objary[0]), Int32.Parse(objary[1]), Int32.Parse(objary[2]));
                        if (loc[0] > 0 && loc[1] > 0)
                        {
                            loc = GeoConvert.encrypt(loc[0], loc[1]);
                            AddMarker(loc[0], loc[1], "history_dot_small_pink.png");
                        }
                    }
                }

                if (mLocList[listBox4.SelectedIndex].cell_count > 1)
                {
                    if (mLocList[listBox4.SelectedIndex].cell_list != null && mLocList[listBox4.SelectedIndex].cell_list.Length > 0)
                    {
                        double[] gdloc = getGDLocation(mLocList[listBox4.SelectedIndex].cell_list.Split(','));
                        if (gdloc[0] > 0)
                        {
                            gdloc = GeoConvert.encrypt(gdloc[0], gdloc[1]);
                            AddMarker(gdloc[0], gdloc[1], "history_dot_small_gd.png");
                        }
                    }
                    
                }
                
                SetBounds();

                string info = string.Format("c_t={0}", mLocList[listBox4.SelectedIndex].c_t);
                addInfoWindow(dloc[0], dloc[1], info);
                addCircle(dloc[0], dloc[1], 500);
            }
            
        }

        private double[] getLocation(int mnc, int lac, int ci)
        {
            double[] loc = new double[2];

            string sqlstr = string.Format("select o_lat, o_lng from t_cell where mnc={0} and lac={1} and cell={2}", mnc, lac, ci);
            conn.Open();
            MySQLCommand comm = new MySQLCommand(sqlstr, conn);
            MySQLDataReader reader = comm.ExecuteReaderEx();
            if (reader.Read())
            {
                loc[0] = (double)reader[0];
                loc[1] = (double)reader[1];
            }
            conn.Close();
            return loc;
        }


        private double[] getGDLocation(string[] celllist)
        {
            double[] loc = new double[2];
            string sQueryNBBuf = "";

            string url = "http://111.206.81.229/APS/r";

            if (celllist.Length >= 2)
            {
                string[] ary = celllist[1].Split('|');
                int mnc = Int32.Parse(ary[0]);
                int lac = Int32.Parse(ary[1]);
                int ci = Int32.Parse(ary[2]);
                int st = Int32.Parse(ary[3]);
                sQueryNBBuf = string.Format("{0},{1},{2}", lac, ci, st);


                for (int i = 2; i < celllist.Length; i++)
                {
                    string[] ary1 = celllist[i].Split('|');
                    int lac1 = Int32.Parse(ary1[1]);
                    int ci1 = Int32.Parse(ary1[2]);
                    int st1 = Int32.Parse(ary1[3]);
                    string sNBItem = string.Format("*{0},{1},{2}", lac1, ci1, st1);
                    sQueryNBBuf += sNBItem;
                }
            }

            string[] ary0 = celllist[0].Split('|');
            int mnc0 = Int32.Parse(ary0[0]);
            int lac0 = Int32.Parse(ary0[1]);
            int ci0 = Int32.Parse(ary0[2]);
            int st0 = Int32.Parse(ary0[3]);
            if (st0 > 0) st0 = st0 - st0 * 2;
            string sQueryBuf = string.Format("<?xml version=\"1.0\" encoding=\"GBK\" ?><Cell_Req ver=\"2.0\"><HDR version=\"2.0\" cdma=\"0\" gtype=\"0\"><src>360kidwrap_nlp_131111</src><serverip>211.151.122.3</serverip><imei>357409039049590</imei><license>BNMLJKBHJWHERE9BHLDEL89NHHN78BH</license></HDR><DRR phnum=\"15810990737\" nettype=\"GPRS\" inftype=\"1\"><mcc>460</mcc><mnc>{0}</mnc><lac>{1}</lac><cellid>{2}</cellid><signal>-{3}</signal><nb>{4}</nb></DRR><Cell_Req>",
                                mnc0, lac0, ci0, st0, sQueryNBBuf);

            Console.Out.WriteLine(string.Format("query string: {0}\n", sQueryBuf));

            ASCIIEncoding encoding = new ASCIIEncoding();
            byte[] data = encoding.GetBytes(sQueryBuf);

            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url); 
            myRequest.Method = "POST";  
            myRequest.ContentType="application/x-www-form-urlencoded"; 
            myRequest.ContentLength = data.Length;  
            Stream newStream=myRequest.GetRequestStream(); 

            // Send the data. 
            newStream.Write(data, 0, data.Length);
            newStream.Close(); 

            // Get response  
            HttpWebResponse myResponse=(HttpWebResponse)myRequest.GetResponse();
            StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.Default);  

            string content = reader.ReadToEnd();
            Console.Out.WriteLine(content);
            int xpos = content.IndexOf("<cenx>");
            int ypos = content.IndexOf("</ceny>");
            if (xpos > 0 || ypos > 0)
            {
                content = content.Substring(xpos + 6, ypos - xpos - 6);
                content = content.Replace("</cenx><ceny>", ",");
                string[] locary = content.Split(',');
                loc[0] = Double.Parse(locary[1]);
                loc[1] = Double.Parse(locary[0]);
            }
            return loc;
        }

        private void btnExportCVS_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            fbd.RootFolder = Environment.SpecialFolder.Desktop;
            if (fbd.ShowDialog() == DialogResult.OK)
            {
                List<string> list = new List<string>();
                foreach (var obj in mLocList)
                {
                    if (obj.cell_count < 2)
                        continue;
                    double[] gdloc = getGDLocation(obj.cell_list.Split(','));
                    for (int k = 0; k < 3; k++)
                    {
                        if(gdloc[0] == 0)
                            gdloc = getGDLocation(obj.cell_list.Split(','));
                        if(gdloc[0] > 0)
                            break;
                        Thread.Sleep(100);
                    }
                    int gdjuli = gdloc[0] > 0 ? (int)LocUtil.distance(obj.lat, obj.lng, gdloc[0], gdloc[1]) : -1;

                    double[] loc = getLocation(obj.mnc, obj.lac, obj.ci);
                    int juli = loc[0] > 0 ? (int)LocUtil.distance(obj.lat, obj.lng, loc[0], loc[1]) : -1;
                    string str = string.Format("{0},{1},{2},{3}", obj.time.ToShortTimeString(), obj.ci, gdjuli, juli);
                    list.Add(str);
                }
               
                string filepath = string.Format("{0}/{1}_{2}.csv", fbd.SelectedPath, txtDeviceID_Loc.Text, txtDate.Text);
                FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate);
                StreamWriter sw = new StreamWriter(fs, Encoding.Default);
                sw.WriteLine(string.Format("\"{0}\",\"{1}\",\"{2}\",\"{3}\"", "time", "cid", "distance", "distance1"));
                foreach (var str in list)
                {
                    sw.WriteLine(str);
                }
                sw.Close();
                fs.Close();
            } 
        }
    }
}
